﻿using IQIGame.Onigao.Framework;
using IQIGame.Onigao.Game;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;


namespace IQIGame.Onigao.GamePlay
{
    public abstract class SNetHandler
    {
        private readonly Dictionary<int, INetServerModule.MessageHandler> cache_messageHandler = new();
        private readonly Dictionary<int, Func<IReceiveMessage>> cache_requestFactory = new();

        public virtual void Init()
        {
        }

        public virtual void Shutdown()
        {
            cache_messageHandler.Clear();
            cache_requestFactory.Clear();
        }

        protected bool Add(INetServerModule mod)
        {
            foreach (var kv in mod.GetModuleFunction())
            {
                cache_messageHandler.Add(kv.Key, kv.Value);
            }
            foreach (var kv in mod.GetModuleRequest())
            {
                cache_requestFactory.Add(kv.Key, kv.Value);
            }
            return true;
        }

        public virtual IReceiveMessage NewRequest(ReceivePackage package)
        {
            int messageId = package.Header.Messagid;
            if (cache_requestFactory.TryGetValue(messageId, out var func))
            {
                IReceiveMessage messageRequest = func.Invoke();
                messageRequest.FromPackage(package);
                return messageRequest;
            }
            else
            {
                LogGame.LogWarning($"SNetHandler not find messageId = {messageId}");
                return null;
            }
        }

        public virtual bool ProcessPackage(ISession session, IReceiveMessage messageRequest)
        {
            MessageResult messageResult = cache_messageHandler[messageRequest.GetMessageId()].Invoke(session, messageRequest);
            if (messageResult == null)
            {
                LogGame.LogError($"Can't return null result messageId = {messageResult.GetMessageId()}");
                return false;
            }
            if (messageResult is VoidMessageResult)
            {
                return true;
            }
            if (messageResult.GetFuture() != null)
            {
                if (messageResult.GetDelayCall() != null)
                {
                    throw new Exception("not support future result set delay call");
                }
                messageResult.GetFuture().ContinueWith(task =>
                {
                    try
                    {
                        MessageResult _result = messageResult.GetFutureResult(task);
                        if (_result.GetFuture() != null)
                        {
                            throw new Exception("not support recursion future result");
                        }
                        if (task.IsFaulted)
                        {
                            LogGame.LogException(task.Exception);
                            _result.SetCode(10001);//服务器异常的错误码
                        }
                        else if (task.IsCanceled)
                        {
                            _result.SetCode(10001);//服务器异常的错误码
                        }
                        NetProtocolHelper.SendMessage(session, _result);
                        _result.GetDelayCall()?.Invoke();
                    }
                    catch (Exception e)
                    {
                        LogGame.LogError(e); 
                    }
                }, TaskScheduler.FromCurrentSynchronizationContext());
            }
            else
            {
                NetProtocolHelper.SendMessage(session, messageResult);
                messageResult.GetDelayCall()?.Invoke();
            }
            return true;
        }
    }
}
